

#include "MyPlayer.h"
#include "MyShots.h"
#include "MyEnemy.h"
#include "MyEnemies.h"
#include "MyEngine.h"
#include "MyUniversal.h"
#include "MyDefinitions.h"
#include "MyGame.h"

//INIT constr/destr, init
MyEnemy::MyEnemy(){}
MyEnemy::MyEnemy(double _x, double _y, enemyType* _thisEnemyType, MyEnemies* _parent):thisEnemyType(_thisEnemyType), parent(_parent), pos_x(0), pos_y(0) { init(_x, _y); }	
MyEnemy::~MyEnemy(){}
void MyEnemy::init(double _x, double _y)
{
	set_pos_dx(_x);
	set_pos_dy(_y);

	set_life(thisEnemyType->life);
	acc_x = acc_y = speed_x = speed_y = moveType = movement_phase = timeMoving = shotWaited = inposition = 0;
	weaponAngle = M_PI * 0.6;
}
/*ENCAPSULATION FUNCTIONS*****************start*/
enemyType* MyEnemy::getType(){return thisEnemyType;}
void MyEnemy::set_pos_dx(double _x){
	//add the diff in x; perform boundary check
	pos_x += _x;	
	if (pos_x < 0) pos_x = 0;
	//if (pos_x > parent->parent->parent->levelW) pos_x = parent->levelW;
	if (pos_x > FIELD_W - this->getType()->w) pos_x = FIELD_W - this->getType()->w;
}
void MyEnemy::set_pos_dy(double _y){
	//add the diff in y
	pos_y += _y;	
	if (pos_y > INFOBAR_Y - this->getType()->h) pos_y = INFOBAR_Y - this->getType()->h;
	if (pos_y < FIELD_Y - this->getType()->h +1 ) pos_y = FIELD_Y - this->getType()->h + 1;	
}
void MyEnemy::set_speed_dx(double _x){
	speed_x += _x;
	if (speed_x >  this->thisEnemyType->speed_constant) speed_x =  this->thisEnemyType->speed_constant;
	if (speed_x < -this->thisEnemyType->speed_constant) speed_x = -this->thisEnemyType->speed_constant;
}
void MyEnemy::set_speed_dy(double _y){
	speed_y += _y;	
	if (speed_y >  this->thisEnemyType->speed_constant) speed_y =  this->thisEnemyType->speed_constant;
	if (speed_y < -this->thisEnemyType->speed_constant) speed_y = -this->thisEnemyType->speed_constant;
}


int MyEnemy::get_life(){return life;}
bool MyEnemy::set_life(int _life){
	life = _life;
	if (life <= 0) return true;
	return false;
}
int MyEnemy::get_damage(){return this->thisEnemyType->dmg;}
/*ENCAPSULATION FUNCTIONS*****************end*/
void MyEnemy::enemy_shoot(int _t)
{
	//can shoot only if pause is over
	if (shotWaited <= 0)
	{
		//shoot right, there he is!
		if (parent->parent->actPlayer->get_pos_x() - pos_x > 0) 
		{
			//add new shot to actProjectils
			parent->parent->actProjectils->add_projectile(pos_x + thisEnemyType->shot_emerge_x_r, pos_y + thisEnemyType->shot_emerge_y_r,
			M_PI - weaponAngle, &(parent->parent->actProjectils->shotTypeArray[thisEnemyType->shootingWhat]),OT_ENEMY, get_damage()); 
		}
		//shoot left, there is player
		else						
		//add new shot to actProjectils
		parent->parent->actProjectils->add_projectile(pos_x+thisEnemyType->shot_emerge_x_l,pos_y+thisEnemyType->shot_emerge_y_l,
		weaponAngle,&(parent->parent->actProjectils->shotTypeArray[thisEnemyType->shootingWhat]),OT_ENEMY, get_damage()); 
		
		shotWaited = thisEnemyType->shotPause;
	}
};
bool MyEnemy::move_enemy(int _t)
{	
	//distance from the player, essencial for shooting
	{	
		if ( //enemy is still too far away
 		(further_than_2D(
		int(parent->parent->actPlayer->get_pos_x()), 
		int(parent->parent->actPlayer->get_pos_y()), 
		int(pos_x), 
		int(pos_y), 
		thisEnemyType->getToDist))
			||
		further_than_1D( //is not in one plane with the player
		int(parent->parent->actPlayer->get_pos_y()), 
		int(pos_y), 7))
		{	
			//get closer
			acc_x = further_than_1D(int(parent->parent->actPlayer->get_pos_x()), int(pos_x), thisEnemyType->getToDist);
			acc_y = further_than_1D(int(parent->parent->actPlayer->get_pos_y()), int(pos_y), 7);
			inposition = false;
		}
		else 
	/*		if (!(further_than_2D( //aby nestrielali ked som prilis blizko, netreba~
				int(parent->parent->actPlayer->get_pos_x()), 
				int(parent->parent->actPlayer->get_pos_y()), 
				int(pos_x), 
				int(pos_y), 
				int(thisEnemyType->getToDist*0.5))))
		{			acc_x = (-1.0*further_than_1D(int(parent->parent->actPlayer->get_pos_x()), int(pos_x), thisEnemyType->getToDist));
			acc_y = (-1.0*further_than_1D(int(parent->parent->actPlayer->get_pos_y()), int(pos_y), 7));
			inposition = false;
		}
		
		else //close enough and on the same plane, shooting possible*/
		{
			acc_x = acc_y = 0;
			inposition = true;
		}
	}

	if (parent->someoneShot) parent->someoneShot -= _t;
	if ((inposition)&&(parent->someoneShot <= 0))
	{
		enemy_shoot(_t);
		parent->someoneShot = 300 + rand() % 100;
	}

	//change the speed accordingly to speedups and movement direction;	
	//slow the enemy down due to the friction etc
	//functions will handle too high speed
	set_speed_dx(acc_x*SPEEDUP_X);
	speed_x	*= FRICTION_X;
	set_speed_dy(acc_y*SPEEDUP_Y);
	speed_y *= FRICTION_Y;	
	//calculate the new position, functions will handle the boundaries
	set_pos_dx(speed_x);
	set_pos_dy(speed_y);
	
	//right = 1, stand = 0, left = -1
	int whereToMove = sgn(acc_x);

	switch(this->moveType)
	{
	case EM_MOVE_RIGHT:
		{
			if (whereToMove == -1)
			{
				moveType = EM_MOVE_LEFT;
				timeMoving = _t;
				movement_phase = 0;
			}
			if (whereToMove == 0)
			{
				moveType = EM_STAND;
				timeMoving = _t;
				movement_phase = 0;
			}
			if (whereToMove == 1)
			{
				timeMoving += _t;
				if (timeMoving > thisEnemyType->phaseDurationMove)
				{
					if (++movement_phase == thisEnemyType->phaseCountMove)
						movement_phase = 0;
					timeMoving -= thisEnemyType->phaseDurationMove;
				}
			}
			break;
		}
	case EM_MOVE_LEFT:
		{
			if (whereToMove == 1)
			{
				moveType = EM_MOVE_RIGHT;
				timeMoving = _t;
				movement_phase = 0;
			}
			if (whereToMove == 0)
			{
				moveType = EM_STAND;
				timeMoving = _t;
				movement_phase = 0;
			}
			if (whereToMove == -1)
			{
				timeMoving += _t;
				if (timeMoving > thisEnemyType->phaseDurationMove)
				{
					if (++movement_phase == thisEnemyType->phaseCountMove)
						movement_phase = 0;
					timeMoving -= thisEnemyType->phaseDurationMove;
				}
			}
			break;
		}
	case EM_STAND:
		{
			if (whereToMove == 1)
			{
				moveType = EM_MOVE_RIGHT;
				timeMoving = _t;
				movement_phase = 0;
			}
			if (whereToMove == 0)
			{
				timeMoving += _t;
				if (timeMoving > thisEnemyType->phaseDurationStand)
				{
					if (++movement_phase == thisEnemyType->phaseCountStand)
						movement_phase = 0;
					timeMoving -= thisEnemyType->phaseDurationStand;
				}
			}
			if (whereToMove == -1)
			{
				moveType = EM_MOVE_LEFT;
				timeMoving = _t;
				movement_phase = 0;
			}
			break;
		}
	case EM_SHOOT:
		{
			break;
		}
	case EM_DIE:
		{
			break;
		}
	}
		
	//decrease the time enemy must wait until next shot
	if (shotWaited > 0) shotWaited -= _t;
	//actual drawing
	draw_enemy();
	return false;
}
void MyEnemy::draw_enemy()
{
	SDL_Rect *tmp1, *tmp2;
	switch(moveType)
	{
		case EM_MOVE_RIGHT:
		{
			tmp1 = make_rect(((thisEnemyType->phaseCountMove-1)-movement_phase)*thisEnemyType->w, 0,thisEnemyType->w, thisEnemyType->h);
			break;
		}
		case EM_MOVE_LEFT:
		{
			tmp1 = make_rect(movement_phase*thisEnemyType->w, thisEnemyType->h,thisEnemyType->w, thisEnemyType->h);
			break;
		}
		case EM_STAND:
		{
			//face the player
			int less_than_zero_means_left = (int)(parent->parent->actPlayer->get_pos_x() - pos_x);
			tmp1 = make_rect(less_than_zero_means_left>0?0:thisEnemyType->w, 2*thisEnemyType->h,thisEnemyType->w, thisEnemyType->h);
			break;
		}
	}
	tmp2 = make_rect((int)pos_x,(int)pos_y,thisEnemyType->w,thisEnemyType->h);
	SDL_BlitSurface(parent->enemySheet[getType()->code],tmp1,parent->parent->parent->screen,tmp2);
	delete(tmp1);
	delete(tmp2);
}
SDL_Rect* MyEnemy::get_hit_zone()
{
	//returns the zone of the enemy to by compared with shot
	if (acc_x < 0) return make_rect(int(pos_x+17), int(pos_y+5), thisEnemyType->w-25,thisEnemyType->h-10); 
	else return make_rect(int(pos_x+10), int(pos_y+5), thisEnemyType->w-25, thisEnemyType->h-10); 
}

//ak by mali nieco robit po smrti --> //parent->parent->actProjectils->add_projectile(get_pos_x(), get_pos_y(), 0, &(parent->parent->actProjectils->shotTypeArray[4]), OT_NOONE);